using System;
using System.Collections.Generic;
using CLELCore.Assembly.BlobStreams;

namespace CLELCore.Assembly.Descriptors.ClassDescriptors
{
	public class GenericTypeDefClassDescriptor : ClassDescriptor
	{
		private CLELAssembly _assembly;
		private byte _generic_type;
		private Token _token;
		private List<ClassDescriptor> _generic_types;

		public Token ClassToken
		{
			get
			{
				return _token.Copy();
			}
		}

		public GenericTypeDefClassDescriptor(CLELAssembly assembly,byte generic_type,Token token,List<ClassDescriptor> generic_types) : base(ClassDescriptor.GENERICTYPEDEF_CLASSDESCRIPTOR)
		{
			if(assembly == null)
				throw new ArgumentException("CLEL assembly cannot be null");
			if(token == null)
				throw new ArgumentException("Class token cannot be null");
			_assembly = assembly;
			_generic_type = generic_type;
			_token = token;
			_generic_types = generic_types;
		}		

		//TODO: Call clel to update token
		public void Update(object sender, EventArgs e)
		{
			//Console.WriteLine(_token);
		}
		
		public override ClassDescriptor Copy()
		{
			return (ClassDescriptor)new GenericTypeDefClassDescriptor(_assembly,_generic_type,_token.Copy(),new List<ClassDescriptor>(_generic_types));
		}

		public override byte [] ToBytes()
		{
			int len = 1;
			byte [] ret;
			byte [] generic_type = Blob.CompressBlobValue(_generic_type);
			len += generic_type.Length;

			byte [] type_token = TokenCompressor.CompressBlobTypeDefOrRefToken(_token);
			int tok = 0;
			if(type_token.Length == 4)
				tok = Bits.MakeInt(type_token[3],type_token[2],type_token[1],type_token[0]);
			else if(type_token.Length == 2)
				tok = Bits.MakeInt(0,0,type_token[1],type_token[0]);
			else
				tok = Bits.MakeInt(0,0,0,type_token[0]);
			type_token = Blob.CompressBlobValue(tok);


			len += type_token.Length;
			byte [] arg_count = Blob.CompressBlobValue(_generic_types.Count);
			len += arg_count.Length;
			byte [][] generic_types = new byte[_generic_types.Count][];
			int i;
			for(i = 0;i < _generic_types.Count;i++)
			{
				generic_types[i] = _generic_types[i].ToBytes();
				len += generic_types[i].Length;
			}

			int next = 1;
			ret = new byte[len];
			ret[0] = BlobElementType.ELEMENT_TYPE_GENERICINST;
			for(i = 0;i < generic_type.Length;i++,next++)
				ret[next] = generic_type[i];
			for(i = 0;i < type_token.Length;i++,next++)
				ret[next] = type_token[i];
			for(i = 0;i < arg_count.Length;i++,next++)
				ret[next] = arg_count[i];
			int j;
			for(j = 0;j < generic_types.Length;j++)
			{
				for(i = 0;i < generic_types[j].Length;i++,next++)
					ret[next] = generic_types[j][i];
			}

			return ret;
		}
	}
}
